package com.lordjoe.collectiveintelligence;

import java.util.*;

/**
 * com.lordjoe.collectiveintelligence.FlightItinery
 *
 * @author Steve Lewis
 * @date Mar 24, 2009
 */
public class FlightItinery
{
    public static FlightItinery[] EMPTY_ARRAY = {};
    public static Class THIS_CLASS = FlightItinery.class;

    private final List<ItineryItem> m_Items = new ArrayList<ItineryItem>();
    private final FlightOptimization m_Problem;
    private final ICostFunction<FlightItinery> m_CostFunction;
    private final double m_Cost;

    public FlightItinery(ItineryItem[] items, FlightOptimization opt,
                         ICostFunction<FlightItinery> cost)
    {
        m_Items.addAll(Arrays.asList(items));
        m_CostFunction = cost;
        m_Cost = cost.computeCost(this);
        m_Problem = opt;
    }

    public ICostFunction<FlightItinery> getCostFunction()
    {
        return m_CostFunction;
    }

    public FlightItinery getCloseItinery()
    {
        return getCloseItinery(1);
    }

    public FlightItinery getCloseItinery(int numberSteps)
    {
        FlightItinery ret = this;
        for (int i = 0; i < numberSteps; i++)
            ret = ret.getOneStepItinery();

        return ret;
    }

    protected FlightItinery getOneStepItinery()
    {
        ItineryItem[] items = getItems();
        int index = FlightOptimization.RND.nextInt(items.length);
        items[index] = getOneStepItinery(items[index]);
        return new FlightItinery(items, getProblem(), getCostFunction());
    }



    public FlightItinery[] getCloseItineries()
    {
        return getCloseItineries(1);
    }


    public FlightItinery[] getCloseItineries(int numberSteps)
    {
        return getOneStepItineries();
    }


    protected FlightItinery[] getOneStepItineries()
    {
        ItineryItem[] items = getItems();
        FlightItinery[] ret = new FlightItinery[items.length];
        for (int i = 0; i < items.length; i++) {
            items = getItems();
            items[i] = getOneStepItinery(items[i]);
            ret[i] =  new FlightItinery(items, getProblem(), getCostFunction());
        }
        return ret;
    }

    protected ItineryItem getOneStepItinery(ItineryItem start)
    {
        String peerson = start.getPerson();
        Flight arrival = start.getArrival();
        Flight aReturn = start.getReturn();
        boolean b = FlightOptimization.RND.nextBoolean();
        if (b)
            arrival = getProblem().selectNewArrival(arrival);
        else
            aReturn = getProblem().selectNewReturn(aReturn);

        return new ItineryItem(peerson, arrival, aReturn);
    }


    public FlightOptimization getProblem()
    {
        return m_Problem;
    }

    public double getCost()
    {
        return m_Cost;
    }

    public ItineryItem[] getItems()
    {
        return m_Items.toArray(ItineryItem.EMPTY_ARRAY);
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        ItineryItem[] item = getItems();
        for (int i = 0; i < item.length; i++) {
            ItineryItem itineryItem = item[i];
            sb.append(itineryItem.toString());
            sb.append("\n");
        }
        return sb.toString();
    }
}
